module Divider #(
    parameter WIDTH = 32,
    parameter W = WIDTH
) (
    input   logic           clock,
    input   logic           reset,
    input   logic [W-1:0]   x,
    input   logic [W-1:0]   y,
    input   logic           div_signed,
    input   logic           valid,
    output  logic           ready,
    output  logic [W-1:0]   q,
    output  logic [W-1:0]   r,
    output  logic           done
);

    assign ready = (state == IDLE);
    assign done  = (state == DONE);

    logic [2*W-1:0] X;
    logic [W-1:0]   Y;
    logic [W-1:0]   Q;
    logic [W-1:0]   R;

    logic div_signed_R;
    logic msb_x_R;
    logic msb_y_R;

    // State Machine
    localparam IDLE = 3'b001, CALC = 3'b010, DONE = 3'b100;
    logic [2:0] state;
    logic [7:0] count;

    always_ff @(posedge clock) begin
        if (reset) begin
            state   <= IDLE;
            count   <= 0;
            X   <= 0;
            Y   <= 0;
            Q   <= 0;
            R   <= 0;
            div_signed_R    <= 0;
            msb_x_R         <= 0;
            msb_y_R         <= 0;
        end
        else begin
            case (state) 
                IDLE: begin
                    if (valid & ready) begin
                        state   <= CALC;
                        count   <= 8'd32;
                        X   <= {{W{1'b0}}, {(div_signed & x[W-1]) ? (~x + 1) : x}};
                        Y   <= (div_signed & y[W-1]) ? (~y + 1) : y;
                        Q   <= 0;
                        R   <= 0;
                        div_signed_R    <= div_signed;
                        msb_x_R         <= x[W-1];
                        msb_y_R         <= y[W-1];
                    end
                    else begin
                        state   <= IDLE;
                    end
                end
                CALC: begin
                    // 继续计算
                    if (|count) begin
                        state   <= CALC;
                        // 负数
                        if (delta[W]) begin
                            // 商为 0
                            Q <= { Q[W-2:0], 1'b0 };
                            // 被除数左移一位
                            X <= { X[2*W-2:0], 1'b0 };
                            R <= X[2*W-2 -: W]; /// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                        end
                        else begin
                            // 商为 1
                            Q   <= { Q[W-2:0], 1'b1 };
                            // 被除数对应部分减去除数, 再左移一位
                            X   <= { delta[W-1:0], X[W-2:0], 1'b0 }; /// !!!
                            R   <= delta[W-1:0];
                        end
                        count   <= count - 1;
                    end
                    // 结束计算
                    else begin
                        state   <= DONE;
                        count   <= 0;
                    end
                end
                DONE: begin
                    state   <= IDLE;
                    div_signed_R   <= 0;
                    msb_x_R        <= 0;
                    msb_y_R        <= 0;
                end
                default: begin
                    state   <= IDLE;
                end
            endcase
        end
    end
    
    wire [W:0] delta = X[2*W-1 -: W+1] - {1'b0, Y};

    assign q = (div_signed_R & (msb_x_R ^ msb_y_R)) ? ~(Q - 1) : Q;
    assign r = (div_signed_R & msb_x_R) ? ~(R - 1) : R;

endmodule // Divider
